import traci
import numpy as np
import random

class controlModel(object):
    def __init__(self, carID):
        self.carID = carID #self的意思是实例对象的本身
        self.type = traci.vehicle.getTypeID(carID)#车辆的类型
        self.speed = traci.vehicle.getSpeed(self.carID)
        self.acc = traci.vehicle.getAcceleration(self.carID)
        [self.x, self.y] = traci.vehicle.getPosition(self.carID)
        self.lane = traci.vehicle.getLaneID(self.carID)#返回所在的车道
        self.vmax = traci.vehicle.getMaxSpeed(self.carID)#最大速度
        self.maxacc = traci.vehicle.getAccel(self.carID)#最大加速度
        self.maxdec = traci.vehicle.getDecel(self.carID)#最大减速度
        self.route = traci.vehicle.getRoute(self.carID)#返回路线
        self.lanePosition = traci.vehicle.getLanePosition(self.carID)#返回车辆已通行距离
        self.length = traci.vehicle.getLength(self.carID)#返回车辆的长度
        self.buslen = 10
        self.carlen = 5
        self.minGap = 1.5#前后车最小间距，相当于文章中的db-carlen
        self.time = traci.simulation.getTime()
        self.pos_next = traci.vehicle.getPosition(self.carID)

    #得到前车id
    def frontCar(self):
        m= 200
        vehicle_frontCarID=""
        for carID in traci.vehicle.getIDList():#对所有的车辆进行遍历
            lanePosition = traci.vehicle.getLanePosition(carID) #获得每个车辆在车道上面的位置
            if traci.vehicle.getLaneID(carID) == self.lane and self.lanePosition < lanePosition < 200: #and之前的这句话的意思是来判断同车道上面的所有的车辆；and后面的这句话则是判断研究车道的前面的这些车
                if lanePosition - self.lanePosition < m: #如果当前车辆与前方车辆之间的距离小于m的话，则说明当前车辆与前方车辆之间的距离更近一点
                    m = lanePosition - self.lanePosition #那么就需要更新这个距离为m的值， 进行下一次遍历，直到遍历完所有的车辆
                    vehicle_frontCarID = carID #那么此时的carID就是研究对象前面的那辆车
        return vehicle_frontCarID

    #相邻车道前车id
    def nearFrontCar(self):
        m= 200
        vehicle_nearFrontCarID_0 = ""#相邻前车在车道0
        vehicle_nearFrontCarID_1 = ""#相邻前车在车道1
        vehicle_nearFrontCarID_2 = ""#相邻前车在车道2
        for carID in traci.vehicle.getIDList(): #对所有的车辆进行遍历
            lanePosition = traci.vehicle.getLanePosition(carID) #获得每个车辆在车道上面的位置
            if self.lane == "gneE1_0" and traci.vehicle.getLaneID(carID) == "gneE1_1" and 200 > lanePosition > self.lanePosition:#找到最右侧车道的相邻车道车辆id
                #前面这句话的意思是当我研究的这辆车在1_0这个车道上面的时候；中间这句话的意思指的是此刻遍历到的这个车在1_1这个车道上，后面这句话的意思是找到1_1车道上在所研究的这辆车前面的车
                if lanePosition - self.lanePosition < m:#和上面的代码逻辑是一样的，通过m，来判断当我这个车在1_0车道的时候，1_1车道上距离研究的这辆车前面最近的那个车
                    m = lanePosition - self.lanePosition
                    vehicle_nearFrontCarID_1 = carID
            elif self.lane == "gneE1_2" and traci.vehicle.getLaneID(carID) == "gneE1_1" and 200 > lanePosition > self.lanePosition:#找到最左侧车道的相邻车道车辆id
                #elif的意思是再次进行判断，代码逻辑和上面的一样
                if lanePosition - self.lanePosition < m:
                    m = lanePosition - self.lanePosition
                    vehicle_nearFrontCarID_1 = carID
            elif self.lane == "gneE1_1" and 200 > lanePosition > self.lanePosition:#找到中间车道的相邻车道车辆id
                #前面这句话的意思是当我研究这辆车在中间这个车道的时候，我先把他前面的所有车辆找到，这个时候找到的所有车辆不单单是这个车道的，而是所有车道的，然后再接下来的程序中进行判断
                if traci.vehicle.getLaneID(carID) == "gneE1_0": #如果遍历到的这个车所在的道路ID是在1_0的话.....
                    if lanePosition - self.lanePosition < m:
                        m = lanePosition - self.lanePosition
                        vehicle_nearFrontCarID_0 = carID
                if traci.vehicle.getLaneID(carID) == "gneE1_2": #如果遍历到的这个车所在的道路ID是在1_2的话.....
                    if lanePosition - self.lanePosition < m:
                        m = lanePosition - self.lanePosition
                        vehicle_nearFrontCarID_2 = carID
        return vehicle_nearFrontCarID_0, vehicle_nearFrontCarID_1, vehicle_nearFrontCarID_2 

    # 相邻车道后车id，逻辑和前面的代码是一样的
    def nearRearCar(self):
        m= 200
        vehicle_nearRearCarID_0 = ""#相邻后车在车道0
        vehicle_nearRearCarID_1 = ""#相邻后车在车道1
        vehicle_nearRearCarID_2 = ""#相邻后车在车道2
        for carID in traci.vehicle.getIDList():
            lanePosition = traci.vehicle.getLanePosition(carID)
            if self.lane == "gneE1_0" and traci.vehicle.getLaneID(carID) == "gneE1_1" and lanePosition < self.lanePosition:#找到最右侧车道的相邻车道车辆id
                if lanePosition - self.lanePosition < m:
                    m = lanePosition - self.lanePosition
                    vehicle_nearRearCarID_1 = carID
            elif self.lane == "gneE1_2" and traci.vehicle.getLaneID(carID) == "gneE1_1" and lanePosition < self.lanePosition:#找到最右侧车道的相邻车道车辆id
                if lanePosition - self.lanePosition < m:
                    m = lanePosition - self.lanePosition
                    vehicle_nearRearCarID_1 = carID
            elif self.lane == "gneE1_1" and lanePosition < self.lanePosition:#找到最右侧车道的相邻车道车辆id
                if traci.vehicle.getLaneID(carID) == "gneE1_0":
                    if lanePosition - self.lanePosition < m:
                        m = lanePosition - self.lanePosition
                        vehicle_nearRearCarID_0 = carID
                if traci.vehicle.getLaneID(carID) == "gneE1_2":
                    if lanePosition - self.lanePosition< m:
                        m = lanePosition - self.lanePosition
                        vehicle_nearRearCarID_2 = carID
        #print(vehicle_nearRearCarID_0, vehicle_nearRearCarID_1, vehicle_nearRearCarID_2)
        return vehicle_nearRearCarID_0, vehicle_nearRearCarID_1, vehicle_nearRearCarID_2

    #生成下一时刻速度
    def speed_generate(self):
        v_next = self.speed
        Pslow, Ps = 0.5, 0.3#慢启动和随机慢化概率
        frontCar =self.frontCar()
        if frontCar != "":  #根据是否存在前车来判断是否去执行特定的代码
            frontCarSpeed = traci.vehicle.getSpeed(frontCar)#获得前车的行驶速度
            frontCarDistance = traci.vehicle.getLanePosition(frontCar)#获得前车行驶通过距离
            minAccSpeed = min(self.speed+self.maxacc, self.vmax)
            if self.speed == 0 and random.uniform(0, 1) < Pslow:#慢启动现象
                v_next = 0 #下一时刻速度为0
            elif frontCarSpeed+frontCarDistance-(minAccSpeed+self.speed)/2-self.lanePosition > self.minGap+self.length:#加速情况
                v_next = minAccSpeed
                if random.uniform(0, 1) < Ps:  # 随机慢化现象
                    v_next = max(v_next - self.maxdec, 0)
            elif frontCarSpeed+frontCarDistance-(minAccSpeed+self.speed)/2-self.lanePosition == self.minGap+self.length:#匀速情况
                if random.uniform(0, 1) < Ps:  # 随机慢化现象
                    v_next = max(v_next - self.maxdec, 0)
            else:#减速情况
                v_next = max(self.speed-self.maxdec, 0)
        return v_next

    #判断是否换道
    def changeLane(self):
        ifChangeLane = False#是否变道
        leftChangeLane = False#向左变道
        rightChangeLane = False#向右变道
        Prc, Plc = 0.6, 0.9
        nearFrontCar_0 = self.nearFrontCar()[0]
        nearFrontCar_1 = self.nearFrontCar()[1]
        nearFrontCar_2 = self.nearFrontCar()[2]
        nearRearCar_0 = self.nearRearCar()[0]
        nearRearCar_1 = self.nearRearCar()[1]
        nearRearCar_2 = self.nearRearCar()[2]
        frontCar = self.frontCar()
        minAccSpeed = min(self.speed + self.maxacc, self.vmax)
        #print(frontCar)
        if self.lane == "gneE1_2" and nearFrontCar_1 != "" and frontCar != "" and nearRearCar_1 != "":
            #相邻车道前车大于本车道前车的距离，相邻车道后车满足安全距离，当前车道受阻，公式13
            if traci.vehicle.getLanePosition(nearFrontCar_1) - self.lanePosition > traci.vehicle.getLanePosition(frontCar) - self.lanePosition\
                    and self.lanePosition - traci.vehicle.getLanePosition(nearRearCar_1) > self.minGap+self.length \
                    and random.uniform(0, 1) <= Prc:
                ifChangeLane = True
        elif self.lane == "gneE1_0" and nearFrontCar_1 != "" and frontCar != "" and nearRearCar_1 != "" and self.type == "car":#只有社会车辆才会变道
            # 相邻车道前车大于本车道前车的距离，相邻车道后车满足安全距离，当前车道受阻，公式16
            if traci.vehicle.getLanePosition(nearFrontCar_1) - self.lanePosition > traci.vehicle.getLanePosition(frontCar) - self.lanePosition\
                    and self.lanePosition - traci.vehicle.getLanePosition(nearRearCar_1) > self.minGap+self.length \
                    and random.uniform(0, 1) <= Plc:
                ifChangeLane = True
        elif self.lane == "gneE1_1" and frontCar != "":
            if nearFrontCar_2 != "" and nearRearCar_2 != "" \
                    and traci.vehicle.getLanePosition(nearFrontCar_2) - self.lanePosition > traci.vehicle.getLanePosition(frontCar) - self.lanePosition\
                    and self.lanePosition - traci.vehicle.getLanePosition(nearRearCar_2) > self.minGap+self.length \
                    and random.uniform(0, 1) <= Plc:#左侧换道
                ifChangeLane = True
                leftChangeLane = True
            elif nearFrontCar_0 != "" and nearRearCar_0 != "" \
                    and traci.vehicle.getLanePosition(nearFrontCar_0) - self.lanePosition > traci.vehicle.getLanePosition(frontCar) - self.lanePosition\
                    and self.lanePosition - traci.vehicle.getLanePosition(nearRearCar_0) > self.minGap+self.length \
                    and random.uniform(0, 1) <= Prc:#右侧换道
                ifChangeLane = True
                rightChangeLane = True
        return ifChangeLane, leftChangeLane, rightChangeLane